# GF_PY3_FLASK3_Workflow_App.py
# Create by GF 2025-04-21

import sys
sys.path.append("./GF_PY3_WORKFLOW_Document_Comparison")
sys.path.append("./GF_PY3_WORKFLOW_AI_Agent_docx_Layout")
sys.path.append("./GF_PY3_WORKFLOW_AI_Agent_Python_PPTX")

# Python 3 Standard Libraries.
import io
import os
import uuid
# ..................................................
import flask
# ..................................................
import GF_PY3_WORKFLOW_Document_Comparison
import GF_PY3_WORKFLOW_AI_Agent_docx_Layout
import GF_PY3_WORKFLOW_AI_Agent_Python_PPTX

# ##################################################

app = flask.Flask(__name__)

# ##################################################

# WWW_HTML_UPLOADS_DIR = "/www/html/uploads"     # Linux
WWW_HTML_UPLOADS_DIR = "C:\\www\\html\\uploads"  # Windows
# os.makedirs(WWW_HTML_UPLOADS_DIR, exist_ok=True)  # 确保上传和临时结果文件夹存在 (不存在则创建)

PPTX_SAVE_DIR = WWW_HTML_UPLOADS_DIR
PPTX_SAVE_URL = "http://127.0.0.1/uploads/"

# 配置上传和临时结果文件夹
# app.config['UPLOAD_FOLDER'] = "/www/html/uploads"         # Linux
# app.config['UPLOAD_FOLDER'] = "C:\\www\\html\\uploads\\"  # Windows

# 设置文件大小限制 (例如 32 MB = 32 * 1024 * 1024)
app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024

# ##################################################

@app.route('/api/document-comparison', methods=['POST'])
def PUSH_POST_API_Document_Comparison():

    # Example:
    # - curl -X POST \
    # -      -H "Accept: text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    # -      -F "file1=@/path/to/example_1.docx" -F "file2=@/path/to/example_2.docx" \
    # -      http://localhost:5000/api/document-comparison
    # -      --output result.csv
    # Returns:
    # - document_comparison_result.csv | document_comparison_result.xlsx

    # 检查两个文件字段是否都存在
    if 'file1' not in flask.request.files or 'file2' not in flask.request.files:
        return {'Error': 'Require 2 Files for Comparison'}, 400

    Requested_Accept = flask.request.headers.get('Accept', '')
    Uploaded_File_1  = flask.request.files['file1']
    Uploaded_File_2  = flask.request.files['file2']
    # ..............................................
    print("[Message] Document Comparison -> File: %s Uploaded Successfully" % Uploaded_File_1.filename)
    print("[Message] Document Comparison -> File: %s Uploaded Successfully" % Uploaded_File_2.filename)

    if Uploaded_File_1.filename == '' or Uploaded_File_2.filename == '':  # 检查文件名是否为空 (Empty)
        return {'Error': "One or Both Files are Empty"}, 400

    # 使用 uuid 生成唯一文件名防止文件名冲突
    # ..............................................
    # file_id = uuid.uuid4().hex
    # Full_Upload_Path = os.path.join(WWW_HTML_UPLOADS_DIR, file_id)
    Full_Upload_Path_1 = os.path.join(WWW_HTML_UPLOADS_DIR, Uploaded_File_1.filename)
    Full_Upload_Path_2 = os.path.join(WWW_HTML_UPLOADS_DIR, Uploaded_File_2.filename)
    Uploaded_File_1.save(Full_Upload_Path_1)
    Uploaded_File_2.save(Full_Upload_Path_2)

    try:

        DC = GF_PY3_WORKFLOW_Document_Comparison.Document_Comparison()

        if (Requested_Accept == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"):
        
            # 调用文档查重函数
            Results_Save_Path = f"{WWW_HTML_UPLOADS_DIR}{os.sep}document_comparison_result.xlsx"
            Execution_Results = DC.Workflow(Full_Upload_Path_1, Full_Upload_Path_2, Results_Save_Path)
            
            # 读取生成的 Excel 文件到内存
            with open(Results_Save_Path, 'rb') as f:
                result_data = io.BytesIO(f.read())
            
            return flask.send_file(  # 返检测结果 (Excel 格式) 文件
                result_data,
                mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                as_attachment=True,
                download_name="document_comparison_result.xlsx"
            )

        else:
        
            # 调用文档查重函数
            Results_Save_Path = f"{WWW_HTML_UPLOADS_DIR}{os.sep}document_comparison_result.csv"
            Execution_Results = DC.Workflow(Full_Upload_Path_1, Full_Upload_Path_2, Results_Save_Path)
            
            # 读取生成的 CSV 文件到内存 (二进制模式 'rb' 读取文件原始字节, 避免不必要的编码/解码步骤)
            with open(Results_Save_Path, 'rb') as f:
                result_data = io.BytesIO(f.read())
            
            return flask.send_file(  # 返检测结果 (CSV 格式) 文件
                result_data,
                mimetype="text/csv",
                as_attachment=True,
                download_name="document_comparison_result.csv"
            )

    except Exception as e:

        print(e)
        return {'error': str(e)}, 500

    finally:

        if os.path.exists(Full_Upload_Path_1):
            os.remove(Full_Upload_Path_1)  # 如果文件已上传, 则清理文件
        if os.path.exists(Full_Upload_Path_2):
            os.remove(Full_Upload_Path_2)

        if 'Results_Save_Path' in locals() and os.path.exists(Results_Save_Path):
            os.remove(Results_Save_Path)  # 结果文件已发送给用户, 则清理文件

@app.route('/api/ai-agent-docx-layout', methods=['POST'])
def PUSH_POST_API_AI_Agent_docx_Layout():

    # Requirement: Flask 3.x.x
    #
    # Example:
    # - curl -H "Content-Type: application/json" \
    # -      -X POST \
    # -      -d '{"messages": [{"role": "user", "content": "请帮我将这些文字归类排版: 搭建全球化供应链平台 ..."}]}' \
    # -      http://127.0.0.1:5000/api/ai-agent-docx-layout
    # Returns:
    # - '{"role": "assistant", "content": "排版优化说明:\n1. 增加了段落间距 (margin) 提升可读性\n2. 通过嵌套结构实现 "设计原则与标准 -> 技术规范 ..."}'
    # 注意事项:
    # - 通过 flask.request.json 获取 POST 数据,
    # - 要求客户端请求头必须是 Content-Type: application/json

    Messages = flask.request.json.get("messages", None)
    # ..............................................
    Rsp_Dict = GF_PY3_WORKFLOW_AI_Agent_docx_Layout.AI_Agent_docx_Layout_Consider_HTML(Messages)
    # ..............................................
    return flask.jsonify(Rsp_Dict), 200, {'Content-Type': 'application/json; charset=utf-8'}

@app.route('/api/ai-agent-python-pptx-code-exec', methods=['POST'])
def PUSH_POST_API_AI_Agent_Python_PPTX_Code_Exec():

    # Requirement: Flask 3.x.x
    #
    # Example:
    # - curl -H "Content-Type: application/json" \
    # -      -X POST \
    # -      -d '{"args": ["/default/patn/1746456033.pptx", "from pptx import Presentation\nprs = Presentation() ..."]}' \
    # -      http://127.0.0.1:5000/api/ai-agent-python-pptx-code-exec
    # Returns:
    # - '{"status": "1|0", "error": "null|code does not include: /default/patn/1746456033.pptx| ..."}'
    # 注意事项:
    # - 通过 flask.request.json 获取 POST 数据,
    # - 要求客户端请求头必须是 Content-Type: application/json

    args = flask.request.json.get("args", None)
    # ..............................................
    if (args[0] not in args[1]):
        print("code does not include: %s" % args[0])
        # ..........................................
        return """{"status": "0", "error": "code does not include: %s", "pptx": "null"}""" % args[0]
    # ..............................................
    args[1] = args[1].replace("/default/patn/", PPTX_SAVE_DIR)
    # ..............................................
    try:
        exec(args[1])  # Python-PPTX 代码执行完毕后, 文件保存在 PPTX_SAVE_DIR, 被替换的 /default/patn/ 只是固定占位符
        # ..........................................                # "/default/patn/1746456033.pptx" -> # "http://127.0.0.1/uploads/1746456033.pptx"
        return """{"status": "1", "error": "null", "pptx": "%s"}""" % args[0].replace("/default/patn/", PPTX_SAVE_DIR)
    except Exception as e:
        print(e)
        # ..............................................
        return """{"status": "0", "error": "%s", "pptx": "null"}""" % str(e)

@app.route('/api/ai-agent-python-pptx', methods=['POST'])
def PUSH_POST_API_AI_Agent_Python_PPTX():

    # Requirement: Flask 3.x.x
    #
    # Example:
    # - curl -H "Content-Type: application/json" \
    # -      -X POST \
    # -      -d '{"messages": [{"role": "user", "content": "有哪些可用的 PPT 模板 ..."}]}' \
    # -      http://127.0.0.1:5000/api/ai-agent-python-pptx
    # Returns:
    # - '{"role": "assistant", "content": "![PPT 模板预览图](http://127.0.0.1/.../example.600.338.4.jpg)\\n模板名称: 潘通蓝时尚简洁\\n\\n适用场景: 工作计划"}'
    # 注意事项:
    # - 通过 flask.request.json 获取 POST 数据,
    # - 要求客户端请求头必须是 Content-Type: application/json

    Messages = flask.request.json.get("messages", None)
    # ..............................................
    Rsp_Dict = GF_PY3_WORKFLOW_AI_Agent_Python_PPTX.Workflow(Messages[0]["content"])
    # ..............................................
    return flask.jsonify(Rsp_Dict), 200, {'Content-Type': 'application/json; charset=utf-8'}

if __name__ == '__main__':

#   app.run(debug=True)  # 调试模式
    app.run(host="0.0.0.0", port=5000)

# EOF Signed by GF.
